<?php
/**
 * Ly - Hy扩展标签类
 *
 * 提供系统需要使用的扩展标签
 *
 * Copyright (c) 2013 YinHailin All rights reserved.
 * @Author: YinHailin
 * @Authorize: Boren Network
 * @Created by YinHailin at 2013-11-01
 */

defined('LY_VERSION') or exit();

class HyTaglib extends Taglib {

  /* 标签列表 */
  protected $Tags = array(
    //标签定义： attr 属性列表 close 是否双标签（0 或者1 默认1） level 嵌套层次 alias 标签别名
    'case' => array('attr' => 'value, break', 'level' => 3),
    'compare' => array('attr'=>'name, value, type', 'level' => 3, 'alias' => 'eq,neq,gt,lt,gte,lte,heq,nheq'),
    'default' => array('close' => 0),
    'else' => array('close' => 0),
    'elseif' => array('attr' => 'condition', 'close' => 0),
    'empty' => array('attr'=>'name', 'level'=>3),
    'if' => array('attr' => 'condition'),
    'notempty' => array('attr'=>'name', 'level'=>3),
    'php' => array(),
    'range' => array('attr' => 'name, value, type', 'level' => 3, 'alias' => 'in,notin,between,notbetween'),
    'volist' => array('attr' => 'name, id, offset, length, key, mod, empty', 'level' => 3, 'alias' => 'iterate'),
    'switch' => array('attr' => 'name', 'level' => 3),
  );

  /*
   * between标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _between($attr, $content) {
    return $this->_range($attr, $content, 'between');
  }

  /*
   * else标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _case($attr, $content) {
    $attrs = $this->ParseXmlAttr($attr, 'case');
    $value = $attrs['value'];
    $break = isset($attrs['break']) ? (bool)$attrs['break'] : true;
    if (substr($value, 1, 1) === '$') {
      //如果为变量
      if (strpos($value, '|') !== false) {
        //如果有变量修饰
        $valueArray = explode('|', $value);
        $value = array_shift($valueArray);
        $value = $this->AutoBuildVar($value);
        if (count($valueArray) > 0) {
          $value = $this->TempEngine->ParseFunction($value, $valueArray);
        }
      }
      $value = 'case '.$value.' :';
    } elseif (strpos($value, '|') !== false) {
      $values = explode('|', $value);
      $value = '';
      foreach ($values as $val) {
        $value .= 'case '.addslashes($val).' :';
      }
    } else {
      $value = 'case '.addslashes($value).' :';
    }
    $parseStr = '<?php '.$value.' ?>'.$content;
    if ($break) {
      $parseStr .= '<?php break; ?>';
    }
    return $parseStr;
  }

  /*
   * compare标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _compare($attr, $content, $type = '==') {
    $attrs = $this->ParseXmlAttr($attr, 'compare');
    $name = $attrs['name'];
    $value = $attrs['value'];
    $type = isset($attrs['type']) ? $attrs['type'] : $type;
    if (strpos($name, '|') !== false) {
      //如果有变量修饰
      $nameArray = explode('|', $name);
      $name = array_shift($nameArray);
      $name = $this->AutoBuildVar($name);
      if (count($nameArray) > 0) {
        $name = $this->TempEngine->ParseFunction($name, $nameArray);
      }
    } else {
      $name = $this->AutoBuildVar($name);
    }
    if (substr($value,0,1) != '$') {
      if (!defined($value)) { $value = '"'.$value.'"';}
    } else {
      if (strpos($value, '|') !== false) {
        //如果有变量修饰
        $valueArray = explode('|', $value);
        $value = array_shift($valueArray);
        $value = $this->AutoBuildVar($value);
        if (count($valueArray) > 0) {
          $value = $this->TempEngine->ParseFunction($value, $valueArray);
        }
      } else {
        $value = $this->AutoBuildVar($value);
      }
    }
    $parseStr = '<?php if (('.$name.') '.$type.' '.$value.') { ?>'.$content.'<?php } ?>';
    return $parseStr;
  }

  /*
   * default标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _default($attr, $content) {
    $parseStr = '<?php default : ?>';
    return $parseStr;
  }

  /*
   * else标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _else($attr, $content) {
    $parseStr = '<?php } else { ?>';
    return $parseStr;
  }

  /*
   * elseif标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _elseif($attr, $content) {
    $attrs = $this->ParseXmlAttr($attr, 'elseif');
    $condition = $attrs['condition'];
    $parseStr = '<?php } elseif ('.$condition.') { ?>';
    return $parseStr;
  }

  /*
   * empty标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _empty($attr, $content) {
    $attrs = $this->ParseXmlAttr($attr, 'empty');
    $name = $attrs['name'];
    $name = $this->AutoBuildVar($name);
    $parseStr = '<?php if (empty('.$name.')) { ?>'.$content.'<?php } ?>';
    return $parseStr;
  }

  /*
   * eq标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _eq($attr, $content) {
    return $this->_compare($attr, $content, '==');
  }

  /*
   * gt标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _gt($attr, $content) {
    return $this->_compare($attr, $content, '>');
  }

  /*
   * gte标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _gte($attr, $content) {
    return $this->_compare($attr, $content, '>=');
  }

  /*
   * heq标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _heq($attr, $content) {
    return $this->_compare($attr, $content, '===');
  }

  /*
   * if标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _if($attr, $content) {
    $attrs = $this->ParseXmlAttr($attr, 'if');
    $condition = $attrs['condition'];
    $parseStr = '<?php if ('.$condition.') { ?>'.$content.'<?php } ?>';
    return $parseStr;
  }

  /*
   * in标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _in($attr, $content) {
    return $this->_range($attr, $content, 'in');
  }

  /*
   * lt标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _lt($attr, $content) {
    return $this->_compare($attr, $content, '<');
  }

  /*
   * lte标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _lte($attr, $content) {
    return $this->_compare($attr, $content, '<=');
  }

  /*
   * neq标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _neq($attr, $content) {
    return $this->_compare($attr, $content, '!=');
  }

  /*
   * nheq标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _nheq($attr, $content) {
    return $this->_compare($attr, $content, '!==');
  }

  /*
   * notbetween标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _notbetween($attr, $content) {
    return $this->_range($attr, $content, 'notbetween');
  }

  /*
   * notempty标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _notempty($attr, $content) {
    $attrs = $this->ParseXmlAttr($attr, 'notempty');
    $name = $attrs['name'];
    $name = $this->AutoBuildVar($name);
    $parseStr = '<?php if (!empty('.$name.')) { ?>'.$content.'<?php } ?>';
    return $parseStr;
  }

  /*
   * notin标签解析
   * @param string $content 标签内容
   * @return string
   */
  public function _notin($attr, $content) {
    return $this->_range($attr, $content, 'notin');
  }

  /*
   * php标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _php($attr, $content) {
    $parseStr = '<?php '.$content.' ?>';
    return $parseStr;
  }

  /*
   * compare标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _range($attr, $content, $type = 'in') {
    $attrs = $this->ParseXmlAttr($attr, 'range');
    $name = $attrs['name'];
    $value = $attrs['value'];
    $type = isset($attrs['type']) ? $attrs['type'] : $type;
    if (strpos($name, '|') !== false) {
      //如果有变量修饰
      $nameArray = explode('|', $value);
      $name = array_shift($nameArray);
      $name = $this->AutoBuildVar($name);
      if (count($nameArray) > 0) {
        $name = $this->TempEngine->ParseFunction($name, $nameArray);
      }
    } else {
      $name = $this->AutoBuildVar($name);
    }
    if (substr($value,0,1) == '$') {
      $value = $this->AutoBuildVar($value);
      $string = 'is_array('.$value.') ? '.$value.' : explode(\',\', '.$value.')';
    } else {
      if (!defined($value)) { $value = '"'.$value.'"';}
      $string = 'explode(\',\', '.$value.')';
    }
    switch ($type) {
      case 'between' :
        $parseStr = '<?php $_hyRangeVar = '.$string.'; if ('.$name.' >= $_hyRangeVar[0] && '.$name.' <= $_hyRangeVar[1]) { ?>'.$content.'<?php } ?>';
        break;
      case 'notbetween' :
        $parseStr = '<?php $_hyRangeVar = '.$string.'; if ('.$name.' < $_hyRangeVar[0] && '.$name.' > $_hyRangeVar[1]) { ?>'.$content.'<?php } ?>';
        break;
      case 'in' :
        $parseStr = '<?php if (in_array('.$name.', '.$string.')) { ?>'.$content.'<?php } ?>';
        break;
      case 'notin' :
        $parseStr = '<?php if (!in_array('.$name.', '.$string.')) { ?>'.$content.'<?php } ?>';
        break;
    }
    return $parseStr;
  }

  /*
   * volist标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _volist($attr, $content) {
    static $_cacheVolistParse = array();
    $identifier = md5($attr.$content);
    //如果解析缓存存在，则直接返回，否则解析后缓存
    if (!isset($_cacheVolistParse[$identifier])) {
      //属性处理
      $attrs = $this->ParseXmlAttr($attr, 'volist');
      $name = $attrs['name'];
      $name = $this->AutoBuildVar($name);
      $id = $attrs['id'];
      $id = $this->AutoBuildVar($id);
      $key = isset($attrs['key']) ? $attrs['key'] : 'k';
      $key = $this->AutoBuildVar($key);
      $i = isset($attrs['count']) ? $attrs['count'] : 'i';
      $i = $this->AutoBuildVar($i);
      $empty = isset($attrs['empty']) ? $attrs['empty'] : '';
      $mod = intval($attrs['mod']);
      $offset = intval($attrs['offset']);
      $length = intval($attrs['length']);

      $parseStr = '<?php ';
      //空数组处理
      $parseStr .= 'if (empty('.$name.')) { echo "'.$empty.'";} else { '.$i.' = 0; ';
      //数组遍历
      $parseStr .= 'foreach ('.$name.' as '.$key.' => '.$id.') { ';
      $parseStr .= $i.'++; ';
      //对count求模运算
      if ($mod > 0) {
        $parseStr .= '$mod = '.$i.' % '.$mod.'; ';
      }
      //偏移输出处理
      if ($offset > 0) {
        $parseStr .= 'if ('.$i.' < '.$offset.') { continue;} ';
      }
      //输出长度处理
      if ($length > 0) {
        $parseStr .= 'if ('.$i.' >= '.($length + $offset).') {'.$i.'--; break;} ';
      }
      $parseStr .= '?>';
      $parseStr .= $content;
      $parseStr .= '<?php } ';
      $parseStr .= '} ?>';

      //写入解析缓存
      $_cacheVolistParse[$identifier] = $parseStr;
    }
    return $_cacheVolistParse[$identifier];
  }

  /*
   * switch标签解析
   * @param string $attr 标签属性
   * @param string $content 标签内容
   * @return string
   */
  public function _switch($attr, $content) {
    $attrs = $this->ParseXmlAttr($attr, 'switch');
    $name = $attrs['name'];
    if (strpos($name, '|') !== false) {
      //如果有变量修饰
      $nameArray = explode('|', $name);
      $name = array_shift($nameArray);
      $name = $this->AutoBuildVar($name);
      if (count($nameArray) > 0) {
        $name = $this->TempEngine->ParseFunction($name, $nameArray);
      }
    } else {
      $name = $this->AutoBuildVar($name);
    }
    $parseStr = '<?php switch('.$name.') { ?>'.$content.'<?php } ?>';
    return $parseStr;
  }
}